package com.jorado.trace.util;


import brave.Span;
import brave.Tracer;
import brave.internal.HexCodec;
import brave.propagation.TraceContext;
import com.jorado.core.utility.SnowFlake;
import com.jorado.core.utility.UniqueIdUtils;
import com.jorado.trace.ZipkinContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class TraceContextUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(TraceContextUtil.class);

    public final static brave.Span initTraceCtx(String serviceName) {
        TraceContext traceCtx = null;
        brave.Span client = null;
        long traceIdHigh = 0, traceIdLow = 0;
        if (ZipkinContext.inst.isInit()) {
            boolean sampled = false;
            // 首先判断当前环境是否已经设置了traceCtx
            Tracer tracer = ZipkinContext.inst.getTracing().tracer();
            // 判断当前的span是否为空
            brave.Span current = tracer.currentSpan();
            if (current != null) {
                client = tracer.newChild(current.context()).name(serviceName).start();
            } else {
                String requestId = RequestID.getRequestID();
                // 直接是客户端调用，需要生成
                if (requestId == null || requestId.length() <= 0) {
                    requestId = UniqueIdUtils.generate();
                    RequestID.setRequestID(requestId);
                    traceIdHigh = HexCodec.lowerHexToUnsignedLong(requestId.substring(0, 16));
                    traceIdLow = HexCodec.lowerHexToUnsignedLong(requestId.substring(16, 32));
                    RequestID.setRequestID(requestId);
                } else {
                    if (requestId.contains("-")) {
                        LOGGER.warn("the trace id contain '-' character!");
                    } else if (requestId.length() < 32) {
                        LOGGER.warn("the trace id's length is less than 32 characters!");
                    } else {
                        traceIdHigh = HexCodec.lowerHexToUnsignedLong(requestId.substring(0, 16));
                        traceIdLow = HexCodec.lowerHexToUnsignedLong(requestId.substring(16, 32));
                    }
                }
                sampled = ZipkinContext.inst.getSampler().isSampled(traceIdLow);
                traceCtx = brave.propagation.TraceContext.newBuilder().traceId(traceIdLow).traceIdHigh(traceIdHigh)
                        .spanId(SnowFlake.getInstance().nextId()).parentId(null).sampled(sampled).build();
                client = tracer.toSpan(traceCtx).name(serviceName).start();
            }

            String requestId = RequestID.getRequestID();
            // 如果不存在traceId,则生成traceId
            if (requestId == null || requestId.length() <= 0) {
                requestId = UniqueIdUtils.generate();
                RequestID.setRequestID(requestId);
            }
            if (requestId.contains("-")) {
                LOGGER.warn("the trace id contain '-' character!");
            } else if (requestId.length() < 32) {
                LOGGER.warn("the trace id's length is less than 32 characters!");
            } else {
                traceIdHigh = HexCodec.lowerHexToUnsignedLong(requestId.substring(0, 16));
                traceIdLow = HexCodec.lowerHexToUnsignedLong(requestId.substring(16, 32));
            }
            client.kind(Span.Kind.CLIENT);
        }
        return client;
    }
}
